﻿/// <summary>
/// Special luminance class which supports ColorImageFrame directly
/// </summary>
using Microsoft.Kinect;

namespace ZXing.Kinect
{
    /// <summary>
    /// special luminance class which supports ColorImageFrame directly
    /// </summary>
    public class KinectColorImageFrameLuminanceSource : RGBLuminanceSource
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="KinectColorImageFrameLuminanceSource"/> class.
        /// </summary>
        /// <param name="width">The width.</param>
        /// <param name="height">The height.</param>
        protected KinectColorImageFrameLuminanceSource(int width, int height)
            : base(width, height)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="KinectColorImageFrameLuminanceSource"/> class.
        /// </summary>
        /// <param name="bitmap">The bitmap.</param>
        public KinectColorImageFrameLuminanceSource(ColorFrame bitmap)
            : this(bitmap, true)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="KinectColorImageFrameLuminanceSource"/> class.
        /// </summary>
        /// <param name="bitmap">The bitmap.</param>
        /// <param name="flipTheImage">if set to <c>true</c> [flip the image].</param>
        public KinectColorImageFrameLuminanceSource(ColorFrame bitmap, bool flipTheImage)
            : base(bitmap.FrameDescription.Width, bitmap.FrameDescription.Height)
        {
            var pixelData = new byte[bitmap.FrameDescription.LengthInPixels];
            var bitmapFormat = BitmapFormat.Unknown;
            switch (bitmap.RawColorImageFormat)
            {
                case ColorImageFormat.Bgra:
                    bitmapFormat = BitmapFormat.BGR32;
                    break;
                default:
                    break;
            }
            bitmap.CopyRawFrameDataToArray(pixelData);
            CalculateLuminance(pixelData, bitmapFormat);
            if (flipTheImage)
            {
                // flip the luminance values because the kinect has it flipped before
                FlipLuminanceValues();
            }
        }

        public KinectColorImageFrameLuminanceSource(MetaKinectPixelData metaPixelData, bool flipTheImage)
            : base(metaPixelData.Width, metaPixelData.Height)
        {
            try
            {
                CalculateLuminance(metaPixelData.PixelData, BitmapFormat.BGR32);
            }
            catch (System.Exception)
            { }
            if (flipTheImage)
            {
                // flip the luminance values because the kinect has it flipped before
                FlipLuminanceValues();
            }
        }
        private void FlipLuminanceValues()
        {
            var width = Width;
            var height = Height;
            var halfWidth = width / 2;

            for (var y = 0; y < height; y++)
            {
                for (var x = 0; x < halfWidth; x++)
                {
                    var posLeft = y * width + x;
                    var posRight = y * width + width - x - 1;
                    var tmp = luminances[posLeft];
                    luminances[posLeft] = luminances[posRight];
                    luminances[posRight] = tmp;
                }
            }
        }

        protected override LuminanceSource CreateLuminanceSource(byte[] newLuminances, int width, int height)
        {
            return new KinectColorImageFrameLuminanceSource(width, height) { luminances = newLuminances };
        }
    }
}